package com.vancouver.knows.ui.activity.userpost;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.pangu.util.StringUtil;
import com.squareup.picasso.Picasso;
import com.stripe.android.Stripe;
import com.stripe.android.TokenCallback;
import com.stripe.android.exception.AuthenticationException;
import com.stripe.android.model.Card;
import com.stripe.android.model.Token;
import com.vancouver.knows.R;
import com.vancouver.knows.business.bean.UserInfo;
import com.vancouver.knows.util.CircleTransform;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnTextChanged;

/**
 * Created by Chris Li on 2016-07-27.
 */
public class PaymentDialog extends Dialog {

    private static final String TAG = PaymentDialog.class.getSimpleName();

    private static final char SPACE_CONSTANT = ' ';
    private static final char SLASH_CONSTANT = '/';
    private static final SimpleDateFormat sFormatter = new SimpleDateFormat("MM/yy", Locale.CANADA);

    private static final String PUBLISHABLE_KEY = "pk_test_sLrCbdAV1TxF4lUocuoGD25E";


    @Bind(R.id.user_avatar)
    ImageView mUserImage;
    @Bind(R.id.user_name)
    TextView mUserName;
    @Bind(R.id.email_input)
    EditText mEmailInput;
    @Bind(R.id.card_number_input)
    EditText mCardNumberInput;
    @Bind(R.id.expiration_input)
    EditText mExpirationInput;
    @Bind(R.id.cvc_input)
    EditText mCvcInput;
    @Bind(R.id.payment_button)
    Button mPaymentButton;
    @Bind(R.id.progress_bar)
    ProgressBar mProgressBar;

    private UserInfo.UserMeta mUserMeta;
    private String mUsernameText;
    private float mPrice;
    private String mLastExpiryInput = "";

    private Stripe mStripe;

    private OnPaymentDialogResultListener mListener;

    public PaymentDialog(Context context, UserInfo.UserMeta userMeta, String username, float uploadCost, OnPaymentDialogResultListener listener) {
        super(context);
        this.mUserMeta = userMeta;
        this.mUsernameText = username;
        this.mPrice = uploadCost;
        this.mListener = listener;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.dialog_payment_view);
        ButterKnife.bind(this);

        if (mUserMeta != null) {
            String avatar = mUserMeta.getAvatar();
            if (!StringUtil.isEmptyString(avatar)) {
                Picasso.with(getOwnerActivity()).load(avatar).transform(new CircleTransform())
                        .fit().into(mUserImage);
            }
            String email = mUserMeta.getEmail();
            if (!StringUtil.isEmptyString(email)) {
                mEmailInput.setText(email);
            }
            mUserName.setText(mUsernameText);
        }

        mProgressBar.setIndeterminate(true);
        mPaymentButton.setText(getContext().getString(R.string.pay_text, new DecimalFormat("#.##").format(mPrice)));

        try {
            this.mStripe = new Stripe(getContext(), PUBLISHABLE_KEY);
        } catch (AuthenticationException e) {
            dismiss();
        }
    }

    @OnClick(R.id.payment_button)
    public void onPaymentButtonClicked() {
        String cardNumber = mCardNumberInput.getText().toString().replace(" ","");
        String cardCvc = mCvcInput.getText().toString();
        String cardExpiration = mExpirationInput.getText().toString();
        String[] cardExpirations = cardExpiration.split("/");
        if (cardExpirations.length == 2) {
            int cardExpMonth = Integer.parseInt(cardExpirations[0]);
            int cardExpYear = Integer.parseInt(cardExpirations[1]);

            Card card = new Card(cardNumber, cardExpMonth, cardExpYear, cardCvc);
            if (card.validateCard()) {
                setCancelable(false);
                mProgressBar.setVisibility(View.VISIBLE);
                mStripe.createToken(card, new TokenCallback() {
                    @Override
                    public void onError(Exception error) {
                        setCancelable(true);
                        Log.e(TAG, error.toString());
                        mProgressBar.setVisibility(View.GONE);
                    }

                    @Override
                    public void onSuccess(Token token) {
                        setCancelable(true);
                        mProgressBar.setVisibility(View.GONE);
                        if (mListener != null) {
                            mListener.onStripeTokenRetrieved(token);
                        }
                        dismiss();
                    }
                });
            }
        }
    }

    public interface OnPaymentDialogResultListener {
        void onStripeTokenRetrieved(Token token);
    }

    @OnTextChanged(value = R.id.card_number_input, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
    public void onCardNumberTextChanged(Editable s) {
        // Remove spacing char
        if (s.length() > 0 && (s.length() % 5) == 0) {
            final char c = s.charAt(s.length() - 1);
            if (SPACE_CONSTANT == c) {
                s.delete(s.length() - 1, s.length());
            }
        }
        // Insert char where needed.
        if (s.length() > 0 && (s.length() % 5) == 0) {
            char c = s.charAt(s.length() - 1);
            if (Character.isDigit(c) && TextUtils.split(s.toString(), String.valueOf(SPACE_CONSTANT)).length <= 3) {
                s.insert(s.length() - 1, String.valueOf(SPACE_CONSTANT));
            }
        }
    }

    @OnTextChanged(value = R.id.expiration_input, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
    public void onExpirationTextChanged(Editable s) {
        String input = s.toString();
        Calendar expiryDate = Calendar.getInstance();
        try {
            expiryDate.setTime(sFormatter.parse(input));
        } catch (ParseException e) {
            try {
                if (s.length() == 2 && !mLastExpiryInput.endsWith("/")) {
                    int month = Integer.parseInt(input);
                    if (month <= 12) {
                        mExpirationInput.setText(mExpirationInput.getText().toString() + SLASH_CONSTANT);
                        mExpirationInput.setSelection(mExpirationInput.getText().toString().length());
                    }
                } else if (s.length() == 2 && mLastExpiryInput.endsWith("/")) {
                    int month = Integer.parseInt(input);
                    if (month <= 12) {
                        mExpirationInput.setText(mExpirationInput.getText().toString().substring(0, 1));
                        mExpirationInput.setSelection(mExpirationInput.getText().toString().length());
                    } else {
                        mExpirationInput.setText("");
                        mExpirationInput.setSelection(mExpirationInput.getText().toString().length());
                    }
                } else if (s.length() == 1) {
                    int month = Integer.parseInt(input);
                    if (month > 1) {
                        mExpirationInput.setText("0" + mExpirationInput.getText().toString() + SLASH_CONSTANT);
                        mExpirationInput.setSelection(mExpirationInput.getText().toString().length());
                    }
                }
            } catch (NumberFormatException e1) {
                mExpirationInput.setText("");
            }

            mLastExpiryInput = mExpirationInput.getText().toString();
        }
    }
}
